package br.academia.negocio;

import org.hibernate.HibernateException;

import br.academia.arq.dao.ExercicioDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Exercicio;
import br.academia.util.Validador;

/** 
 * Processador para validação de negócio de operações
 * relacionadas a Exercicio
 * 
 * @see Exercicio
 */
public class ExercicioProcessador extends AbstractProcessador<Exercicio>{

	@Override
	public void execute(TipoOperacao operacao, Exercicio obj) throws NegocioException{
		try {
			if(operacao.equals(CADASTRAR)){
				validarCadastro(obj);
				cadastrar(obj);
			}else if(operacao.equals(ALTERAR)){
				validarAlteracao(obj);
				alterar(obj);
			}else if(operacao.equals(REMOVER)){
				validarRemocao(obj);
				remover(obj);
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new NegocioException("Não foi possível realizar a operação. Contate a administração do sistema.");
		} catch (DAOException e) {
			throw new NegocioException(e.getMessage());
		}
	}
	
	/**
	 * Método que valida se o nome setado em um Exercicio já tem um correspondente
	 * com relação à sigla, no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void validarNome(Exercicio obj) throws NegocioException, HibernateException, DAOException{
		ExercicioDAO dao = null;
		boolean erro = false;
		
		try {
			dao = getDAO(ExercicioDAO.class);
			
			Exercicio modalidade = dao.findExercicioByNome(obj.getNome());
			
			if(!Validador.isEmpty(modalidade)){
				if(modalidade.getId() != obj.getId()){
					erro = true;
				}
			}
			
			if(erro){
				throw new NegocioException("Um outro Exercicio já foi cadastrado com o nome \"" + obj.getNome() + "\".");
			}
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para o cadastro
	 * de um Exercicio novo no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarCadastro(Exercicio obj) throws HibernateException, NegocioException, DAOException{
		validarNome(obj);
	}
	
	/**
	 * Método que insere um Exercicio no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void cadastrar(Exercicio obj) throws NegocioException, HibernateException, DAOException{
		ExercicioDAO dao = null;
		
		try {
			dao = getDAO(ExercicioDAO.class);
			
			dao.save(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a alteração
	 * de um Exercicio no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarAlteracao(Exercicio obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou um Exercicio inválido.");
		}else{
			ExercicioDAO dao = null;
			Exercicio exercicio = null;
			
			try {
				dao = getDAO(ExercicioDAO.class);
				
				exercicio = dao.findExercicioByNome(obj.getNome());
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(!Validador.isEmpty(exercicio)){
				validarNome(obj);
			}
		}
	}
	
	/**
	 * Método que atualiza um Exercicio no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void alterar(Exercicio obj) throws NegocioException, HibernateException, DAOException{
		ExercicioDAO dao = null;
		
		try {
			dao = getDAO(ExercicioDAO.class);
			
			dao.update(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a remoção
	 * de um Exercicio no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarRemocao(Exercicio obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou um Exercicio inválido.");
		}else{
			ExercicioDAO dao = null;
			Exercicio exercicio = null;
			
			try {
				dao = getDAO(ExercicioDAO.class);
				
				exercicio = dao.findByPrimaryKey(obj.getId(), Exercicio.class);
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(Validador.isEmpty(exercicio)){
				throw new NegocioException("Não foi possível encontrar o Exercicio selecionado no nosso banco de dados.");
			}
		}
	}
	
	/**
	 * Método que remove um Exercicio do banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void remover(Exercicio obj) throws NegocioException, HibernateException, DAOException{
		ExercicioDAO dao = null;
		
		try {
			dao = getDAO(ExercicioDAO.class);
			
			dao.delete(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
}
